use super::*;

#[derive(Debug, Default, Clone)]
pub struct FontInfo {
	// Generic Identification Information↩
	pub family_name: String, // Family name. Note: The specification is agnostic about how this value relates to openTypeNamePreferredFamilyName.
	pub style_name: String, // Style name. Note: The specification is agnostic about how this value relates to openTypeNamePreferredSubfamilyName.
	pub style_map_family_name: String, // Family name used for bold, italic and bold italic style mapping.
	pub style_map_style_name: String, // Style map style. The possible values are regular, italic, bold and bold italic. These are case sensitive.
	pub version_major: Integer,       // Major version.
	pub version_minor: UInteger,      // Minor version.
	pub year: Integer, // The year the font was created. This attribute is deprecated as of version 2. Its presence should not be relied upon by authoring tools. However, it may occur in a font’s info so authoring tools should preserve it if present.
	// Generic Legal Information
	pub copyright: String, //Copyright statement.
	pub trademark: String, // Trademark statement.
	// Generic Dimension Information
	pub units_per_em: UIntegerOrFloat, // Units per em.
	pub descender: IntegerOrFloat, // Descender value. Note: The specification is agnostic about the relationship to the more specific vertical metric values.
	pub x_height: IntegerOrFloat,  // x-height value.
	pub cap_height: IntegerOrFloat, // Cap height value.
	pub ascender: IntegerOrFloat, // Ascender value. Note: The specification is agnostic about the relationship to the more specific vertical metric values.
	pub italic_angle: IntegerOrFloat, // Italic angle. This must be an angle in counter-clockwise degrees from the vertical.
	// Generic Miscellaneous Information
	pub note: String, //Arbitrary note about the font.
	// OpenType gasp Table Fields
	pub opentype_gasp_range_records: Vec<GaspRange>, // A list of gasp Range Records. These must be sorted in ascending order based on the rangeMaxPPEM value of the record.
	// OpenType head Table Fields
	pub opentype_head_created: String, // Creation date. Expressed as a string of the format “YYYY/MM/DD HH:MM:SS”. “YYYY/MM/DD” is year/month/day. The month must be in the range 1-12 and the day must be in the range 1-end of month. “HH:MM:SS” is hour:minute:second. The hour must be in the range 0:23. The minute and second must each be in the range 0-59. The timezone is UTC.
	pub opentype_head_lowest_rec_ppem: UInteger, // Smallest readable size in pixels. Corresponds to the OpenType head table lowestRecPPEM field.
	pub opentype_head_flags: Vec<UInteger>, // A list of bit numbers indicating the flags. The bit numbers are listed in the OpenType head specification. Corresponds to the OpenType head table flags field.
	// OpenType hhea Table Fields
	pub opentype_hhea_ascender: Integer, // Ascender value. Corresponds to the OpenType hhea table Ascender field.
	pub opentype_hhea_descender: Integer, // Descender value. Corresponds to the OpenType hhea table Descender field.
	pub opentype_hhea_line_gap: Integer, // Line gap value. Corresponds to the OpenType hhea table LineGap field.
	pub opentype_hhea_caret_slope_rise: Integer, // Caret slope rise value. Corresponds to the OpenType hhea table caretSlopeRise field.
	pub opentype_hhea_caret_slope_run: Integer, // Caret slope run value. Corresponds to the OpenType hhea table caretSlopeRun field.
	pub opentype_hhea_caret_offset: Integer, // Caret offset value. Corresponds to the OpenType hhea table caretOffset field.
	// OpenType Name Table Fields
	pub opentype_name_designer: String, // Designer name. Corresponds to the OpenType name table name ID 9.
	pub opentype_name_designer_url: String, // URL for the designer. Corresponds to the OpenType name table name ID 12.
	pub opentype_name_manufacturer: String, // Manufacturer name. Corresponds to the OpenType name table name ID 8.
	pub opentype_name_manufacturer_url: String, // Manufacturer URL. Corresponds to the OpenType name table name ID 11.
	pub opentype_name_license: String,  // License text. Corresponds to the OpenType name table name ID 13.
	pub opentype_name_license_url: String, // URL for the license. Corresponds to the OpenType name table name ID 14.
	pub opentype_name_version: String,  // Version string. Corresponds to the OpenType name table name ID 5.
	pub opentype_name_unique_id: String, // Unique ID string. Corresponds to the OpenType name table name ID 3.
	pub opentype_name_description: String, // Description of the font. Corresponds to the OpenType name table name ID 10.
	pub opentype_name_preferred_family_name: String, // Preferred family name. Corresponds to the OpenType name table name ID 16.
	pub opentype_name_preferred_subfamily_name: String, // Preferred subfamily name. Corresponds to the OpenType name table name ID 17.
	pub opentype_name_compatible_full_name: String, // Compatible full name. Corresponds to the OpenType name table name ID 18.
	pub opentype_name_sample_text: String, // Sample text. Corresponds to the OpenType name table name ID 19.
	pub opentype_name_wwsfamily_name: String, // WWS family name. Corresponds to the OpenType name table name ID 21.
	pub opentype_name_wwssubfamily_name: String, // WWS Subfamily name. Corresponds to the OpenType name table name ID 22.
	pub opentype_name_records: Vec<NameRecord>, // A list of name records. This name record storage area is intended for records that require platform, encoding and or language localization.
	// OpenType OS/2 Table Fields
	pub opentype_os2_width_class: UInteger, // Width class value. Must be in the range 1-9. Corresponds to the OpenType OS/2 table usWidthClass field.
	pub opentype_os2_weight_class: UInteger, // Weight class value. Corresponds to the OpenType OS/2 table usWeightClass field.
	pub opentype_os2_selection: Vec<UInteger>, // A list of bit numbers indicating the bits that should be set in fsSelection. The bit numbers are listed in the OpenType OS/2 specification. Corresponds to the OpenType OS/2 table selection field. Note: Bits 0 (italic), 5 (bold) and 6 (regular) must not be set here. These bits should be taken from the generic styleMapStyleName attribute.
	pub opentype_os2_vendor_id: String, // Four character identifier for the creator of the font. Corresponds to the OpenType OS/2 table achVendID field.
	pub opentype_os2_panose: Vec<UInteger>, // The list must contain 10 non-negative integers that represent the setting for each category in the Panose specification. The integers correspond with the option numbers in each of the Panose categories. This corresponds to the OpenType OS/2 table Panose field.
	pub opentype_os2_family_class: Vec<Integer>, // Two integers representing the IBM font class and font subclass of the font. The first number, representing the class ID, must be in the range 0-14. The second number, representing the subclass, must be in the range 0-15. The numbers are listed in the OpenType OS/2 specification. Corresponds to the OpenType OS/2 table sFamilyClass field.
	pub opentype_os2_unicode_ranges: Vec<UInteger>, // A list of bit numbers that are supported Unicode ranges in the font. The bit numbers are listed in the OpenType OS/2 specification. Corresponds to the OpenType OS/2 table ulUnicodeRange1, ulUnicodeRange2, ulUnicodeRange3 and ulUnicodeRange4 fields.
	pub opentype_os2_code_page_ranges: Vec<UInteger>, // A list of bit numbers that are supported code page ranges in the font. The bit numbers are listed in the OpenType OS/2 specification. Corresponds to the OpenType OS/2 table ulCodePageRange1 and ulCodePageRange2 fields.
	pub opentype_os2_typo_ascender: Integer,          // Ascender value. Corresponds to the OpenType OS/2 table sTypoAscender field.
	pub opentype_os2_typo_descender: Integer,         // Descender value. Corresponds to the OpenType OS/2 table sTypoDescender field.
	pub opentype_os2_typo_line_gap: Integer,          // Line gap value. Corresponds to the OpenType OS/2 table sTypoLineGap field.
	pub opentype_os2_win_ascent: UInteger,            // Ascender value. Corresponds to the OpenType OS/2 table usWinAscent field.
	pub opentype_os2_win_descent: UInteger,           // Descender value. Corresponds to the OpenType OS/2 table usWinDescent field.
	pub opentype_os2_type: Vec<UInteger>, // A list of bit numbers indicating the embedding type. The bit numbers are listed in the OpenType OS/2 specification. Corresponds to the OpenType OS/2 table fsType field.
	pub opentype_os2_subscript_xsize: Integer, // Subscript horizontal font size. Corresponds to the OpenType OS/2 table ySubscriptXSize field.
	pub opentype_os2_subscript_ysize: Integer, // Subscript vertical font size. Corresponds to the OpenType OS/2 table ySubscriptYSize field.
	pub opentype_os2_subscript_xoffset: Integer, // Subscript x offset. Corresponds to the OpenType OS/2 table ySubscriptXOffset field.
	pub opentype_os2_subscript_yoffset: Integer, // Subscript y offset. Corresponds to the OpenType OS/2 table ySubscriptYOffset field.
	pub opentype_os2_superscript_xsize: Integer, // Superscript horizontal font size. Corresponds to the OpenType OS/2 table ySuperscriptXSize field.
	pub opentype_os2_superscript_ysize: Integer, // Superscript vertical font size. Corresponds to the OpenType OS/2 table ySuperscriptYSize field.
	pub opentype_os2_superscript_xoffset: Integer, // Superscript x offset. Corresponds to the OpenType OS/2 table ySuperscriptXOffset field.
	pub opentype_os2_superscript_yoffset: Integer, // Superscript y offset. Corresponds to the OpenType OS/2 table ySuperscriptYOffset field.
	pub opentype_os2_strikeout_size: Integer,    // Strikeout size. Corresponds to the OpenType OS/2 table yStrikeoutSize field.
	pub opentype_os2_strikeout_position: Integer, // Strikeout position. Corresponds to the OpenType OS/2 table yStrikeoutPosition field.
	// OpenType vhea Table Fields
	pub opentype_vhea_vert_typo_ascender: Integer, // Ascender value. Corresponds to the OpenType vhea table vertTypoAscender field.
	pub opentype_vhea_vert_typo_descender: Integer, // Descender value. Corresponds to the OpenType vhea table vertTypoDescender field.
	pub opentype_vhea_vert_typo_line_gap: Integer, // Line gap value. Corresponds to the OpenType vhea table vertTypoLineGap field.
	pub opentype_vhea_caret_slope_rise: Integer,   // Caret slope rise value. Corresponds to the OpenType vhea table caretSlopeRise field.
	pub opentype_vhea_caret_slope_run: Integer,    // Caret slope run value. Corresponds to the OpenType vhea table caretSlopeRun field.
	pub opentype_vhea_caret_offset: Integer,       // Caret offset value. Corresponds to the OpenType vhea table caretOffset field.
	// PostScript Specific Data
	pub postscript_font_name: String,           // Name to be used for the FontName field in Type 1/CFF table.
	pub postscript_full_name: String,           // Name to be used for the FullName field in Type 1/CFF table.
	pub postscript_slant_angle: IntegerOrFloat, // Artificial slant angle. This must be an angle in counter-clockwise degrees from the vertical. This value is not the same as the italic angle. Font authoring tools may use this value to set the FontMatrix in Type 1/CFF table.
	pub postscript_unique_id: Integer,          // A unique ID number as defined in the Type 1/CFF specification.
	pub postscript_underline_thickness: IntegerOrFloat, // Underline thickness value. Corresponds to the Type 1/CFF/post table UnderlineThickness field.
	pub postscript_underline_position: IntegerOrFloat, // Underline position value. Corresponds to the Type 1/CFF/post table UnderlinePosition field. Note: This value is ambiguous as post/CFF2 defines this position from the top, and Type 1/CFF defines it from the middle of the underline. The result of this value depends on which definition a compiler uses.
	pub postscript_is_fixed_pitch: bool, // Indicates if the font is monospaced. An authoring tool could calculate this automatically, but the designer may wish to override this setting. This corresponds to the Type 1/CFF isFixedPitched field
	pub postscript_blue_values: Vec<IntegerOrFloat>, // A list of up to 14 integers or floats specifying the values that should be in the Type 1/CFF BlueValues field. This list must contain an even number of integers following the rules defined in the Type 1/CFF specification.
	pub postscript_other_blues: Vec<IntegerOrFloat>, // A list of up to 10 integers or floats specifying the values that should be in the Type 1/CFF OtherBlues field. This list must contain an even number of integers following the rules defined in the Type 1/CFF specification.
	pub postscript_family_blues: Vec<IntegerOrFloat>, //A list of up to 14 integers or floats specifying the values that should be in the Type 1/CFF FamilyBlues field. This list must contain an even number of integers following the rules defined in the Type 1/CFF specification.
	pub postscript_family_other_blues: Vec<IntegerOrFloat>, // A list of up to 10 integers or floats specifying the values that should be in the Type 1/CFF FamilyOtherBlues field. This list must contain an even number of integers following the rules defined in the Type 1/CFF specification.
	pub postscript_stem_snap_h: Vec<IntegerOrFloat>, // List of horizontal stems sorted in the order specified in the Type 1/CFF specification. Up to 12 integers or floats are possible. This corresponds to the Type 1/CFF StemSnapH field.
	pub postscript_stem_snap_v: Vec<IntegerOrFloat>, // List of vertical stems sorted in the order specified in the Type 1/CFF specification. Up to 12 integers or floats are possible. This corresponds to the Type 1/CFF StemSnapV field.
	pub postscript_blue_fuzz: IntegerOrFloat,        // BlueFuzz value. This corresponds to the Type 1/CFF BlueFuzz field.
	pub postscript_blue_shift: IntegerOrFloat,       // BlueShift value. This corresponds to the Type 1/CFF BlueShift field.
	pub postscript_blue_scale: f64,                  // BlueScale value. This corresponds to the Type 1/CFF BlueScale field.
	pub postscript_force_bold: bool,                 // Indicates how the Type 1/CFF ForceBold field should be set.
	pub postscript_default_width_x: IntegerOrFloat,  // Default width for glyphs.
	pub postscript_nominal_width_x: IntegerOrFloat,  // Nominal width for glyphs.
	pub postscript_weight_name: String, // A string indicating the overall weight of the font. This corresponds to the Type 1/CFF Weight field. It should have a reasonable value that reflects the openTypeOS2WeightClass value.
	pub postscript_default_character: String, // The name of the glyph that should be used as the default character in PFM files.
	pub postscript_windows_character_set: Integer, // The Windows character set. The values are defined below.
	// Macintosh FOND Resource Data
	pub macintosh_fondfamily_id: Integer, // Family ID number. Corresponds to the ffFamID in the FOND resource.
	pub macintosh_fondname: String,       // Font name for the FOND resource.
	// WOFF Data
	pub woff_major_version: UInteger,                         // Major version of the font.
	pub woff_minor_version: UInteger,                         // Minor version of the font.
	pub woff_metadata_unique_id: WOFFMetadataUniqueID, // Identification string. Corresponds to the WOFF uniqueid. The dictionary must follow the WOFF Metadata Unique ID Record structure.
	pub woff_metadata_vendor: WOFFMetadataVendor, // Font vendor. Corresponds to the WOFF vendor element. The dictionary must follow the the WOFF Metadata Vendor Record structure.
	pub woff_metadata_credits: WOFFMetadataCredits, // Font credits. Corresponds to the WOFF credits element. The dictionary must follow the WOFF Metadata Credits Record structure.
	pub woff_metadata_description: WOFFMetadataDescription, // Font description. Corresponds to the WOFF description element. The dictionary must follow the WOFF Metadata Description Record structure.
	pub woff_metadata_license: WOFFMetadataLicense, // Font license. Corresponds to the WOFF license element. The dictionary must follow the WOFF Metadata License Record structure.
	pub woff_metadata_copyright: WOFFMetadataCopyright, // Font copyright. Corresponds to the WOFF copyright element. The dictionary must follow the WOFF Metadata Copyright Record structure.
	pub woff_metadata_trademark: WOFFMetadataTrademark, // Font trademark. Corresponds to the WOFF trademark element. The dictionary must follow the WOFF Metadata Trademark Record structure.
	pub woff_metadata_licensee: WOFFMetadataLicensee, // Font licensee. Corresponds to the WOFF licensee element. The dictionary must follow the WOFF Metadata Licensee Record structure.
	pub woff_metadata_extensions: Vec<WOFFMetadataExtension>, // List of metadata extension records. The dictionaries must follow the WOFF Metadata Extension Record structure. There must be at least one extension record in the list.
	// Guidelines
	pub guidelines: Vec<Guideline>, // A list of guideline definitions that apply to all glyphs in all layers in the font. This attribute is optional.
}

impl FromPlist for FontInfo {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			let token = r.next()?;
			match token {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"familyName" => this.family_name = r.string()?,
					"styleName" => this.style_name = r.string()?,
					"styleMapFamilyName" => this.style_map_family_name = r.string()?,
					"styleMapStyleName" => this.style_map_style_name = r.string()?,
					"versionMajor" => this.version_major = r.integer()?,
					"versionMinor" => this.version_minor = r.uinteger()?,
					"year" => this.year = r.integer()?,
					//
					"copyright" => this.copyright = r.string()?,
					"trademark" => this.trademark = r.string()?,
					//
					"unitsPerEm" => this.units_per_em = r.uinteger_or_float()?,
					"descender" => this.descender = r.integer_or_float()?,
					"xHeight" => this.x_height = r.integer_or_float()?,
					"capHeight" => this.cap_height = r.integer_or_float()?,
					"ascender" => this.ascender = r.integer_or_float()?,
					"italicAngle" => this.italic_angle = r.integer_or_float()?,
					//
					"note" => this.note = r.string()?,
					//
					"openTypeGaspRangeRecords" => this.opentype_gasp_range_records = r.read()?,
					//
					"openTypeHeadCreated" => this.opentype_head_created = r.string()?,
					"openTypeHeadLowestRecPPEM" => this.opentype_head_lowest_rec_ppem = r.uinteger()?,
					"openTypeHeadFlags" => this.opentype_head_flags = r.array()?,
					//
					"openTypeHheaAscender" => this.opentype_hhea_ascender = r.integer()?,
					"openTypeHheaDescender" => this.opentype_hhea_descender = r.integer()?,
					"openTypeHheaLineGap" => this.opentype_hhea_line_gap = r.integer()?,
					"openTypeHheaCaretSlopeRise" => this.opentype_hhea_caret_slope_rise = r.integer()?,
					"openTypeHheaCaretSlopeRun" => this.opentype_hhea_caret_slope_run = r.integer()?,
					"openTypeHheaCaretOffset" => this.opentype_hhea_caret_offset = r.integer()?,
					//
					"openTypeNameDesigner" => this.opentype_name_designer = r.string()?,
					"openTypeNameDesignerURL" => this.opentype_name_designer_url = r.string()?,
					"openTypeNameManufacturer" => this.opentype_name_manufacturer = r.string()?,
					"openTypeNameManufacturerURL" => this.opentype_name_manufacturer_url = r.string()?,
					"openTypeNameLicense" => this.opentype_name_license = r.string()?,
					"openTypeNameLicenseURL" => this.opentype_name_license_url = r.string()?,
					"openTypeNameVersion" => this.opentype_name_version = r.string()?,
					"openTypeNameUniqueID" => this.opentype_name_unique_id = r.string()?,
					"openTypeNameDescription" => this.opentype_name_description = r.string()?,
					"openTypeNamePreferredFamilyName" => this.opentype_name_preferred_family_name = r.string()?,
					"openTypeNamePreferredSubfamilyName" => this.opentype_name_preferred_subfamily_name = r.string()?,
					"openTypeNameCompatibleFullName" => this.opentype_name_compatible_full_name = r.string()?,
					"openTypeNameSampleText" => this.opentype_name_sample_text = r.string()?,
					"openTypeNameWWSFamilyName" => this.opentype_name_wwsfamily_name = r.string()?,
					"openTypeNameWWSSubfamilyName" => this.opentype_name_wwssubfamily_name = r.string()?,
					"openTypeNameRecords" => this.opentype_name_records = r.read()?,
					//
					"openTypeOS2WidthClass" => this.opentype_os2_width_class = r.uinteger()?,
					"openTypeOS2WeightClass" => this.opentype_os2_weight_class = r.uinteger()?,
					"openTypeOS2Selection" => this.opentype_os2_selection = r.array()?,
					"openTypeOS2VendorID" => this.opentype_os2_vendor_id = r.string()?,
					"openTypeOS2Panose" => this.opentype_os2_panose = r.array()?,
					"openTypeOS2FamilyClass" => this.opentype_os2_family_class = r.array()?,
					"openTypeOS2UnicodeRanges" => this.opentype_os2_unicode_ranges = r.array()?,
					"openTypeOS2CodePageRanges" => this.opentype_os2_code_page_ranges = r.array()?,
					"openTypeOS2TypoAscender" => this.opentype_os2_typo_ascender = r.integer()?,
					"openTypeOS2TypoDescender" => this.opentype_os2_typo_descender = r.integer()?,
					"openTypeOS2TypoLineGap" => this.opentype_os2_typo_line_gap = r.integer()?,
					"openTypeOS2WinAscent" => this.opentype_os2_win_ascent = r.uinteger()?,
					"openTypeOS2WinDescent" => this.opentype_os2_win_descent = r.uinteger()?,
					"openTypeOS2Type" => this.opentype_os2_type = r.array()?,
					"openTypeOS2SubscriptXSize" => this.opentype_os2_subscript_xsize = r.integer()?,
					"openTypeOS2SubscriptYSize" => this.opentype_os2_subscript_ysize = r.integer()?,
					"openTypeOS2SubscriptXOffset" => this.opentype_os2_subscript_xoffset = r.integer()?,
					"openTypeOS2SubscriptYOffset" => this.opentype_os2_subscript_yoffset = r.integer()?,
					"openTypeOS2SuperscriptXSize" => this.opentype_os2_superscript_xsize = r.integer()?,
					"openTypeOS2SuperscriptYSize" => this.opentype_os2_superscript_ysize = r.integer()?,
					"openTypeOS2SuperscriptXOffset" => this.opentype_os2_superscript_xoffset = r.integer()?,
					"openTypeOS2SuperscriptYOffset" => this.opentype_os2_superscript_yoffset = r.integer()?,
					"openTypeOS2StrikeoutSize" => this.opentype_os2_strikeout_size = r.integer()?,
					"openTypeOS2StrikeoutPosition" => this.opentype_os2_strikeout_position = r.integer()?,
					//
					"openTypeVheaVertTypoAscender" => this.opentype_vhea_vert_typo_ascender = r.integer()?,
					"openTypeVheaVertTypoDescender" => this.opentype_vhea_vert_typo_descender = r.integer()?,
					"openTypeVheaVertTypoLineGap" => this.opentype_vhea_vert_typo_line_gap = r.integer()?,
					"openTypeVheaCaretSlopeRise" => this.opentype_vhea_caret_slope_rise = r.integer()?,
					"openTypeVheaCaretSlopeRun" => this.opentype_vhea_caret_slope_run = r.integer()?,
					"openTypeVheaCaretOffset" => this.opentype_vhea_caret_offset = r.integer()?,
					//
					"postscriptFontName" => this.postscript_font_name = r.string()?,
					"postscriptFullName" => this.postscript_full_name = r.string()?,
					"postscriptSlantAngle" => this.postscript_slant_angle = r.integer_or_float()?,
					"postscriptUniqueID" => this.postscript_unique_id = r.integer()?,
					"postscriptUnderlineThickness" => this.postscript_underline_thickness = r.integer_or_float()?,
					"postscriptUnderlinePosition" => this.postscript_underline_position = r.integer_or_float()?,
					"postscriptIsFixedPitch" => this.postscript_is_fixed_pitch = r.bool()?,
					"postscriptBlueValues" => this.postscript_blue_values = r.array()?,
					"postscriptOtherBlues" => this.postscript_other_blues = r.array()?,
					"postscriptFamilyBlues" => this.postscript_family_blues = r.array()?,
					"postscriptFamilyOtherBlues" => this.postscript_family_other_blues = r.array()?,
					"postscriptStemSnapH" => this.postscript_stem_snap_h = r.array()?,
					"postscriptStemSnapV" => this.postscript_stem_snap_v = r.array()?,
					"postscriptBlueFuzz" => this.postscript_blue_fuzz = r.integer_or_float()?,
					"postscriptBlueShift" => this.postscript_blue_shift = r.integer_or_float()?,
					"postscriptBlueScale" => this.postscript_blue_scale = r.float()?,
					"postscriptForceBold" => this.postscript_force_bold = r.bool()?,
					"postscriptDefaultWidthX" => this.postscript_default_width_x = r.integer_or_float()?,
					"postscriptNominalWidthX" => this.postscript_nominal_width_x = r.integer_or_float()?,
					"postscriptWeightName" => this.postscript_weight_name = r.string()?,
					"postscriptDefaultCharacter" => this.postscript_default_character = r.string()?,
					"postscriptWindowsCharacterSet" => this.postscript_windows_character_set = r.integer()?,
					//
					"macintoshFONDFamilyID" => this.macintosh_fondfamily_id = r.integer()?,
					"macintoshFONDName" => this.macintosh_fondname = r.string()?,
					//
					"woffMajorVersion" => this.woff_major_version = r.uinteger()?,
					"woffMinorVersion" => this.woff_minor_version = r.uinteger()?,
					"woffMetadataUniqueID" => this.woff_metadata_unique_id = r.read()?,
					"woffMetadataVendor" => this.woff_metadata_vendor = r.read()?,
					"woffMetadataCredits" => this.woff_metadata_credits = r.read()?,
					"woffMetadataDescription" => this.woff_metadata_description = r.read()?,
					"woffMetadataLicense" => this.woff_metadata_license = r.read()?,
					"woffMetadataCopyright" => this.woff_metadata_copyright = r.read()?,
					"woffMetadataTrademark" => this.woff_metadata_trademark = r.read()?,
					"woffMetadataLicensee" => this.woff_metadata_licensee = r.read()?,
					"woffMetadataExtensions" => this.woff_metadata_extensions = r.array()?,
					//
					"guidelines" => this.guidelines = r.array()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Default, Clone)]
pub struct GaspRange {
	pub range_max_ppem: UInteger, // The upper limit of the range, in PPEM. If any records are in the list, the final record should use 65535 (0xFFFF) as defined in the OpenType gasp specification. Corresponds to the rangeMaxPPEM field of the GASPRANGE record in the OpenType gasp table.
	pub range_gasp_behavior: Vec<UInteger>, // A list of bit numbers indicating the flags to be set. The bit numbers are defined below. Corresponds to the rangeGaspBehavior field of the GASPRANGE record in the OpenType gasp table.
}
impl FromPlist for GaspRange {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"rangeMaxPPEM" => this.range_max_ppem = r.uinteger()?,
					"rangeGaspBehavior" => this.range_gasp_behavior = r.array()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct NameRecord {
	pub name_id: UInteger,     // The name ID.
	pub platform_id: UInteger, // The platform ID.
	pub encoding_id: UInteger, // The encoding ID.
	pub language_id: UInteger, // The language ID.
	pub string: String,        // The string value for the record.
}
impl FromPlist for NameRecord {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"nameID" => this.name_id = r.uinteger()?,
					"platformID" => this.platform_id = r.uinteger()?,
					"encodingID" => this.encoding_id = r.uinteger()?,
					"languageID" => this.language_id = r.uinteger()?,
					"string" => this.string = r.string()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct Guideline {
	pub x: Option<IntegerOrFloat>, // The ‘x’ coordinate. Optional if y is provided and angle is not provided. See below for details.	None
	pub y: Option<IntegerOrFloat>, // The ‘y’ coordinate. Optional if x is provided and angle is not provided. See below for details.	None
	pub angle: Option<IntegerOrFloat>, // The angle of the guideline. This must be an angle between 0 and 360 degrees in a counter-clockwise direction from the horizontal. If x or y are not specified, angle must not be specified. See below for details.	None.
	pub name: Option<String>,          // An arbitrary name for the guideline. This attribute is optional.	no name
	pub color: Option<String>, // The color that should be applied to the guideline. The format follows the color definition standard. This attribute is optional.	no color
	pub identifier: Option<String>, // Unique identifier for the guideline. This attribute is not required and should only be added to guidelines as needed. However, once an identifier has been assigned to a guideline it must not be unnecessarily removed or changed. Identifiers may be changed in incoming guidelines during editing operations such as “paste,” but they should be maintained unless a duplicate identifier will be created. The identifier value must be unique within the fontinfo.plist guidelines list that the guideline belongs to but it is not required to be unique among the identifiers assigned to guidelines in glyphs. The identifier specification is detailed in the conventions.	no identifier
}
impl FromPlist for Guideline {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"x" => this.x = r.integer_or_float()?.into(),
					"y" => this.y = r.integer_or_float()?.into(),
					"angle" => this.angle = r.integer_or_float()?.into(),
					"name" => this.name = r.string()?.into(),
					"color" => this.color = r.string()?.into(),
					"identifier" => this.identifier = r.string()?.into(),
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataUniqueID {
	pub id: String, // The id. This is required.
}
impl FromPlist for WOFFMetadataUniqueID {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"id" => this.id = r.string()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataVendor {
	pub name: String,  // Font vendor. Corresponds to the WOFF vendor element name attribute. This is required.
	pub url: String,   // Font vendor URL. Corresponds to the WOFF vendor element url attribute. This is optional.
	pub dir: String, // Writing direction. The options are ltr and rtl. Corresponds to the WOFF vendor element dir attribute. This is optional.
	pub class: String, // Class tokens. Corresponds to the WOFF vendor element class attribute. This is optional.
}
impl FromPlist for WOFFMetadataVendor {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"name" => this.name = r.string()?,
					"url" => this.url = r.string()?,
					"dir" => this.dir = r.string()?,
					"class" => this.class = r.string()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataCredits {
	pub credits: Vec<WOFFMetadataCredit>, // Font credits. Corresponds to the WOFF credits element. The items in the list must follow the WOFF Credit Record format. The list must contain at least one credit record.
}
impl FromPlist for WOFFMetadataCredits {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"credits" => this.credits = r.array()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataCredit {
	pub name: String,  // The name for the credit. Corresponds to the WOFF credit element name attribute. This is required.
	pub url: String,   // The url for the credit. Corresponds to the WOFF credit element url attribute. This is optional.
	pub role: String,  // The role for the credit. Corresponds to the WOFF credit element role attribute. This is optional.
	pub dir: String, // Writing direction. The options are ltr and rtl. Corresponds to the WOFF credit element dir attribute. This is optional.
	pub class: String, // Class tokens. Corresponds to the WOFF credit element class attribute. This is optional.
}
impl FromPlist for WOFFMetadataCredit {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"name" => this.name = r.string()?,
					"url" => this.url = r.string()?,
					"role" => this.role = r.string()?,
					"dir" => this.dir = r.string()?,
					"class" => this.class = r.string()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataDescription {
	pub url: String, // A URL for the description. Corresponds to the WOFF description element url attribute. This is optional.
	pub text: Vec<WOFFMetadataText>, // A list of WOFF Metadata Text Records for the description. This list must contain at least one text record.
}
impl FromPlist for WOFFMetadataDescription {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"url" => this.url = r.string()?,
					"text" => this.text = r.array()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataLicense {
	pub url: String, // A URL for the license. Corresponds to the WOFF license element url attribute. This is optional.
	pub id: String,  // Ad ID for the license. Corresponds to the WOFF license element id attribute. This is optional.
	pub text: Vec<WOFFMetadataText>, // A list of WOFF Metadata Text Records for the description. The list is permitted to be empty.
}
impl FromPlist for WOFFMetadataLicense {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"url" => this.url = r.string()?,
					"id" => this.id = r.string()?,
					"text" => this.text = r.array()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataCopyright {
	pub text: Vec<WOFFMetadataText>, // A list of WOFF Metadata Text Records for the copyright. This list must contain at least one text record.
}
impl FromPlist for WOFFMetadataCopyright {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"text" => this.text = r.array()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataTrademark {
	pub text: Vec<WOFFMetadataText>, // A list of WOFF Metadata Text Records for the copyright. This list must contain at least one text record.
}
impl FromPlist for WOFFMetadataTrademark {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"text" => this.text = r.array()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataLicensee {
	pub name: String,  // The licensee. Corresponds to the WOFF licensee element name attribute. This is required.
	pub dir: String, // Writing direction. The options are ltr and rtl. Corresponds to the WOFF vendor element dir attribute. This is optional.
	pub class: String, // Class tokens. Corresponds to the WOFF licensee element class attribute. This is optional.
}
impl FromPlist for WOFFMetadataLicensee {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"name" => this.name = r.string()?,
					"dir" => this.dir = r.string()?,
					"class" => this.class = r.string()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataText {
	pub text: String,     // The text for the record. This is required.
	pub language: String, // Language. Corresponds to the WOFF text element xml:lang attribute. This is optional.
	pub dir: String, // Writing direction. The options are ltr and rtl. Corresponds to the WOFF text element dir attribute. This is optional.
	pub class: String, // Class tokens. Corresponds to the WOFF text element class attribute. This is optional.
}
impl FromPlist for WOFFMetadataText {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"text" => this.text = r.string()?,
					"language" => this.language = r.string()?,
					"dir" => this.dir = r.string()?,
					"class" => this.class = r.string()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataExtension {
	pub id: String,                            // The id for the extension. This is optional.
	pub names: Vec<WOFFMetadataExtensionName>, // List of WOFF Metadata Extension Name Records.
	pub items: Vec<WOFFMetadataExtensionItem>, // List of WOFF Metadata Extension Item Records. The list must contain at least one item record.
}
impl FromPlist for WOFFMetadataExtension {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"id" => this.id = r.string()?,
					"names" => this.names = r.array()?,
					"items" => this.items = r.array()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataExtensionItem {
	pub id: String,                              // The id of the item record.
	pub names: Vec<WOFFMetadataExtensionName>, // List of WOFF Metadata Extension Name Records. The list must contain at least one name record.
	pub values: Vec<WOFFMetadataExtensionValue>, // List of WOFF Metadata Extension Value Records. The list must contain at least one value record.
}
impl FromPlist for WOFFMetadataExtensionItem {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"id" => this.id = r.string()?,
					"names" => this.names = r.array()?,
					"values" => this.values = r.array()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataExtensionName {
	pub text: String,     // The name of the name record. This is required.
	pub language: String, // The language of the name record. This is optional.
	pub dir: String, // Writing direction. The options are ltr and rtl. Corresponds to the WOFF extension name element dir attribute. This is optional.
	pub class: String, // Class tokens. Corresponds to the WOFF extension name element class attribute. This is optional.
}
impl FromPlist for WOFFMetadataExtensionName {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"text" => this.text = r.string()?,
					"language" => this.language = r.string()?,
					"dir" => this.dir = r.string()?,
					"class" => this.class = r.string()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}

#[derive(Debug, Clone, Default)]
pub struct WOFFMetadataExtensionValue {
	pub text: String,     // The value of the value record. This is required.
	pub language: String, // The language of the value record. This is optional.
	pub dir: String, // Writing direction. The options are ltr and rtl. Corresponds to the WOFF extension value element dir attribute. This is optional.
	pub class: String, // Class tokens. Corresponds to the WOFF extension value element class attribute. This is optional.
}
impl FromPlist for WOFFMetadataExtensionValue {
	fn from_plist(r: &mut Parser<'_, '_, '_>) -> Result<Self, Error> {
		r.dict_start()?;
		let mut this = Self::default();
		loop {
			match r.next()? {
				plist::Event::End => break,
				plist::Event::Error(e, _) => return Err(Error::Plist(e)),
				plist::Event::Key(key) => match key {
					"text" => this.text = r.string()?,
					"language" => this.language = r.string()?,
					"dir" => this.dir = r.string()?,
					"class" => this.class = r.string()?,
					_ => r.skip_value()?,
				},
				_ => return Err(Error::Msg("expect key")),
			}
		}
		Ok(this)
	}
}
